<template>
  <div class="max-w-4xl mx-auto p-6">
    <h1 class="text-2xl font-semibold">大小写转换（Case Convert）</h1>
    <p class="mt-4 text-gray-600">对文本进行常见的大小写转换：全部大写、全部小写、首字母大写、句首大写、切换大小写等。</p>

    <div class="mt-6 space-y-4">
      <div class="flex items-center space-x-3">
        <label class="text-sm text-gray-700">转换类型：</label>
        <select v-model="mode" class="border rounded px-2 py-1">
          <option value="upper">全部大写（UPPERCASE）</option>
          <option value="lower">全部小写（lowercase）</option>
          <option value="capitalizeWords">每词首字母大写（Capitalize Words）</option>
          <option value="sentence">句首大写（Sentence case）</option>
          <option value="title">标题式（Title Case）</option>
          <option value="toggle">切换大小写（Toggle Case）</option>
          <option value="camel">camelCase</option>
          <option value="snake">snake_case</option>
          <option value="kebab">kebab-case</option>
        </select>

        <label class="ml-4 flex items-center space-x-2 text-sm">
          <input type="checkbox" v-model="trimLines" class="form-checkbox" />
          <span>去除行首尾空白（Trim lines）</span>
        </label>
      </div>

      <div class="flex space-x-4">
        <div class="flex-1">
          <div class="flex items-center justify-between mb-2">
            <label class="text-sm font-medium">输入</label>
            <div class="space-x-2">
              <button @click="pasteFromClipboard" class="text-sm text-blue-500">粘贴</button>
              <input ref="fileInput" type="file" accept=".txt" class="hidden" @change="onFileChange" />
              <button @click="() => $refs.fileInput.click()" class="text-sm text-blue-500">打开文件</button>
            </div>
          </div>
          <textarea v-model="inputText" rows="12" class="w-full border rounded p-2" placeholder="在此输入或粘贴文本"></textarea>
        </div>

        <div class="flex-1">
          <div class="flex items-center justify-between mb-2">
            <label class="text-sm font-medium">输出</label>
            <div class="space-x-2">
              <button @click="copyOutput" class="text-sm text-blue-500">复制</button>
              <button @click="downloadOutput" class="text-sm text-blue-500">下载</button>
            </div>
          </div>
          <textarea :value="outputText" rows="12" readonly class="w-full border rounded p-2 bg-gray-50"></textarea>
        </div>
      </div>

      <div class="flex items-center space-x-3">
        <button @click="processNow" class="primary-button">立即转换</button>
        <button @click="applyOutput" class="secondary-button">用输出替换输入</button>
        <button @click="clearAll" class="border px-3 py-2 rounded">清空</button>
        <nuxt-link to="/text-tools" class="ml-auto text-sm text-blue-500">返回文本工具</nuxt-link>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, watch, onMounted } from 'vue'
import { useTools } from '~/composables/useTools'

const { copyToClipboard, downloadFile, readFile, debounce } = useTools()

const inputText = ref('')
const outputText = ref('')
const mode = ref('upper')
const trimLines = ref(false)
const fileInput = ref(null)

// Unicode-aware helpers
const toUpper = (s) => s.toUpperCase()
const toLower = (s) => s.toLowerCase()

const capitalizeWord = (w) => {
  if (!w) return ''
  const [first, ...rest] = [...w]
  return first.toUpperCase() + rest.join('').toLowerCase()
}

const capitalizeWords = (text) => {
  return text.replace(/([\p{L}\p{N}_'\-]+)/gu, (m) => capitalizeWord(m))
}

const sentenceCase = (text) => {
  // 将整个文本先小写，再对每个句子首字母大写
  const lower = text.toLowerCase()
  return lower.replace(/(^|[.!?]\s+)([\p{L}])/gu, (m, p1, p2) => p1 + p2.toUpperCase())
}

const titleCase = (text) => {
  // 简单的 title case：每个单词首字母大写
  return text.replace(/([\p{L}\p{N}_'\-]+)/gu, (m) => capitalizeWord(m))
}

const toggleCase = (text) => {
  return [...text].map(ch => {
    const up = ch.toUpperCase()
    const low = ch.toLowerCase()
    if (ch === up) return low
    if (ch === low) return up
    return ch
  }).join('')
}

const toCamel = (text) => {
  const parts = text.split(/[^\p{L}\p{N}]+/u).filter(Boolean)
  return parts.map((p, i) => i === 0 ? p.toLowerCase() : capitalizeWord(p)).join('')
}

const toSnake = (text) => {
  const parts = text.split(/[^\p{L}\p{N}]+/u).filter(Boolean)
  return parts.map(p => p.toLowerCase()).join('_')
}

const toKebab = (text) => {
  const parts = text.split(/[^\p{L}\p{N}]+/u).filter(Boolean)
  return parts.map(p => p.toLowerCase()).join('-')
}

const processNow = () => {
  let raw = inputText.value || ''
  if (trimLines.value) {
    raw = raw.split(/\r?\n/).map(l => l.trim()).join('\n')
  }

  switch (mode.value) {
    case 'upper':
      outputText.value = toUpper(raw)
      break
    case 'lower':
      outputText.value = toLower(raw)
      break
    case 'capitalizeWords':
      outputText.value = capitalizeWords(raw)
      break
    case 'sentence':
      outputText.value = sentenceCase(raw)
      break
    case 'title':
      outputText.value = titleCase(raw)
      break
    case 'toggle':
      outputText.value = toggleCase(raw)
      break
    case 'camel':
      outputText.value = toCamel(raw)
      break
    case 'snake':
      outputText.value = toSnake(raw)
      break
    case 'kebab':
      outputText.value = toKebab(raw)
      break
    default:
      outputText.value = raw
  }
}

const debouncedProcess = debounce(processNow, 200)

watch([inputText, mode, trimLines], () => {
  debouncedProcess()
})

const copyOutput = async () => {
  if (!outputText.value) return
  const ok = await copyToClipboard(outputText.value)
  if (!ok) alert('复制失败，请手动复制')
}

const downloadOutput = () => {
  if (!outputText.value) return
  downloadFile(outputText.value, 'case-convert.txt', 'text/plain')
}

const pasteFromClipboard = async () => {
  try {
    const text = await navigator.clipboard.readText()
    inputText.value = text
  } catch (e) {
    console.error('读取剪贴板失败', e)
  }
}

const onFileChange = async (e) => {
  const file = e.target.files && e.target.files[0]
  if (!file) return
  try {
    const content = await readFile(file)
    inputText.value = content
  } catch (err) {
    console.error('读取文件失败', err)
    alert('读取文件失败')
  } finally {
    e.target.value = ''
  }
}

const clearAll = () => {
  inputText.value = ''
  outputText.value = ''
}

const applyOutput = () => {
  inputText.value = outputText.value
}

onMounted(() => {
  processNow()
})
</script>

